package com.thh.ftp.service.impl;
import com.thh.ftp.config.FtpConfig;
import com.thh.ftp.mapper.SysFileMapper;
import com.thh.ftp.pojo.SysFile;
import com.thh.ftp.service.SysFileService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.thh.ftp.util.FTPUtils;
import com.thh.ftp.util.Md5Utils;
import com.thh.ftp.util.ValidationData;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.el.util.Validation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/****
 * @Author:thh
 * @Description:SysFile业务层接口实现类
 * @Date 2019/12/11 14:39
 *****/
@Service
public class SysFileServiceImpl implements SysFileService {

    @Autowired(required = false)
    private SysFileMapper sysFileMapper;

    @Autowired
    private FtpConfig ftpConfig;

    @Value("${ftp.upload-location}")
    String upload_location;

    @Override
    public SysFile upload(MultipartFile multipartFile, HttpServletRequest request, Long userId) {

        SysFile sysFile = new SysFile();
        //封装参数
        Map<String, String[]> map = request.getParameterMap();

      //  String fileMd5 = request.getParameter("fileMd5");
        String md5 = UUID.randomUUID().toString().replace("-","");
        String fileMd5 = Md5Utils.getMd5(md5);

        try {
            BeanUtils.populate(sysFile, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        String fileExt  =StringUtils.getFilenameExtension(multipartFile.getOriginalFilename());
        //绝对路径  目前用的是ftp 所以不需要去判断 也不需要去创建  在ftpClient创建了项目路径
        String fileFolderPath = getFileFolderPath(fileMd5);
        String filePath =this.getFilePath(fileMd5,fileExt);
       // File file = new File(filePath);
       // boolean exists = file.exists();
        SysFile dbSysFile = sysFileMapper.selectByPrimaryKey(fileMd5);
        if ( dbSysFile!=null){
            //文件存在
            throw new RuntimeException("上传文件在系统已存在");
        }
        //文件不存在时做一些准备工作 检查目录是否存在 如果不存在 则创建

       /* File fileFolder = new File(fileFolderPath);
        if (!fileFolder.exists()){
            fileFolder.mkdirs();
        }*/
        //校验前端传回的参数
        validationSysFileData(sysFile);

        //初始化参数
        SysFile initSysFile =  initSysFileData(sysFile,multipartFile,fileMd5);

        FTPClient client = FTPUtils.getClient(ftpConfig);
        boolean uploadResult = FTPUtils.upload(client, multipartFile,initSysFile.getFilePath() ,initSysFile.getFileName());
        FTPUtils.close(client);
        if (uploadResult){
            sysFileMapper.insertSelective(initSysFile);
            return initSysFile;
        }else {
            throw new RuntimeException("上传失败！");
        }
    }

    @Override
    public PageInfo getList(int page,int size,Map searchMap) {
        PageHelper.startPage(page,size);
        List<SysFile> sysFileList = sysFileMapper.selectByExample(null);
        return new PageInfo(sysFileList);
    }

    @Override
    public PageInfo getMyList(int page,int size,Map searchMap, Long userId) {
        PageHelper.startPage(page,size);
        SysFile sysFile = new SysFile();
        sysFile.setUploadUserId(userId);
        List<SysFile> sysFileList = sysFileMapper.select(sysFile);
        return new PageInfo(sysFileList);
    }

    //得到文件所属目录路径
    private String getFileFolderPath(String fileMd5){
        return  upload_location + fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/";
    }
    //得到文件的路径
    private String getFilePath(String fileMd5,String fileExt){
        return upload_location + fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" + fileMd5 + "." +fileExt;
    }


    /**
     * 初始化数据
     */
    private SysFile initSysFileData(SysFile sysFile,MultipartFile multipartFile,String fileMd5) {
        String originalFilename = multipartFile.getOriginalFilename();
        String fileExt = StringUtils.getFilenameExtension(multipartFile.getOriginalFilename());
        sysFile.setId(fileMd5);
        sysFile.setFileName(fileMd5+"."+fileExt);//文件名称
        sysFile.setFileOriginalName(originalFilename+"."+fileExt);//文件原始名称
        //文件路径保存相对路径
        String filePath = fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/";
        sysFile.setFilePath(filePath);
        sysFile.setFileSize(multipartFile.getSize());
        sysFile.setFileUrl(filePath+sysFile.getFileName());//文件url
        sysFile.setPostfix(fileExt);//文件后缀
        sysFile.setContentType(multipartFile.getContentType());
        sysFile.setState(1);
        sysFile.setUploadUserId(1L);
        sysFile.setUploadUserName("测试");
        sysFile.setUploadTime(new Date());
        sysFile.setDownloadCount(0L);
        return sysFile;

    }

    /**
     * 校验参数
     */
    private void validationSysFileData(SysFile sysFile) {
        ValidationData.ValidationIsNotEmpty(sysFile.getTag());//业务主键
        ValidationData.ValidationIsNotEmpty(sysFile.getType());//业务主键
    }

    @Override
    public ResponseEntity<byte[]> download(HttpServletResponse response, String id) {
        SysFile dbSysFile = sysFileMapper.selectByPrimaryKey(id);

        HttpStatus statusCode = HttpStatus.NOT_FOUND;//设置404
        HttpHeaders headers = new HttpHeaders();

        if (dbSysFile.getState() == 1) {//判断文件是否可下载
            String fileOriginalName = dbSysFile.getFileOriginalName();//文件文件名
            /************************设置文件请求头************************************/
            headers.add("Content-Type", dbSysFile.getContentType());
            try {
                headers.add("Content-Disposition", "attchement;filename=" + URLEncoder.encode(fileOriginalName, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        ResponseEntity<byte[]>   entity = down(dbSysFile, headers, statusCode);
        return entity;
    }

    @Override
    public ResponseEntity<byte[]> show(HttpServletResponse response, String id) {

        SysFile dbSysFile = sysFileMapper.selectByPrimaryKey(id);
        HttpHeaders headers = new HttpHeaders();
        HttpStatus statusCode = HttpStatus.NOT_FOUND;//设置404
        String fileOriginalName = dbSysFile.getFileOriginalName();//文件文件名
        /************************设置文件************************************/
        headers.add("Content-Type", dbSysFile.getContentType());

        /***************************END*************************************/

        if (dbSysFile.getState() == 1) {//文件不可下载时防止浏览器缓存
            /************************防止用户浏览器缓存中下载********************************/
            response.setDateHeader("Expires", 0);
            response.setHeader("Buffer", "True");
            response.setHeader("Cache-Control", "no-store");
            response.setHeader("Expires", "0");
            response.setHeader("ETag", String.valueOf(System.currentTimeMillis()));
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Date", String.valueOf(new Date()));
            response.setHeader("Last-Modified", String.valueOf(new Date()));
            /*******************************END**********************************************/
        }
        ResponseEntity<byte[]> entity = down(dbSysFile, headers, statusCode);

        return entity;
    }

    private ResponseEntity<byte[]> down(SysFile dbSysFile,HttpHeaders headers,HttpStatus statusCode){
        //拼接文件全路径              2/b/2b03939b7ff2c6150423f41b3662de87/2b03939b7ff2c6150423f41b3662de87.jpg
        String fileUrl = ("/" + dbSysFile.getFileUrl());
        //获取FTP客户端
        FTPClient ftpClient = FTPUtils.getClient(ftpConfig);
        //获取文件流
        byte[] body = FTPUtils.download(ftpClient, fileUrl);
        //关闭
        FTPUtils.close(ftpClient);
        //设置响应结果
        if (body != null) {
            dbSysFile.setDownloadCount(dbSysFile.getDownloadCount()+1);
            sysFileMapper.updateByPrimaryKeySelective(dbSysFile);
            statusCode = HttpStatus.OK;
        }
        return new ResponseEntity<byte[]>(body, headers, statusCode);

    }


    @Override
    public SysFile deleteFake(String id) {
        SysFile sysFile = sysFileMapper.selectByPrimaryKey(id);
        if (sysFile==null||sysFile.getState()!=1){
            throw  new RuntimeException("已经被删除，无法重复删除");
        }
        //设置状态为待删除
        sysFile.setState(3);
        //设置删除时间为15天以后
        sysFile.setDeleteDate(new Date(System.currentTimeMillis() + (1000 * 60 * 60 * 24 * 15)));
        //修改
        int count = sysFileMapper.updateByPrimaryKey(sysFile);
        //判断是否修改成功
        if (count == 1) {
            return sysFile;
        } else {
           throw  new RuntimeException("删除失败");
        }
    }

    @Override
    public SysFile deleteReal(String id) {

        SysFile sysFile = sysFileMapper.selectByPrimaryKey(id);
        if (sysFile==null||sysFile.getState()!=1){
            throw  new RuntimeException("已经被删除，无法重复删除");
        }
            //获取FTP客户端
            FTPClient ftpClient = FTPUtils.getClient(ftpConfig);
            //拼接文件
            String filePath = ("/"+sysFile.getFilePath());
            String fileName = sysFile.getFileName();
            //获取文件流
            boolean isDelete = FTPUtils.delete(ftpClient, filePath,fileName);
            //关闭
            FTPUtils.close(ftpClient);
            if (isDelete) {
                //设置状态为删除
                sysFile.setState(0);
                //修改
                int count = sysFileMapper.updateByPrimaryKeySelective(sysFile);
                //判断是否修改成功
                if (count == 1) {
                   return sysFile;
                } else {
                    return null;
                }
            } else {
               throw new RuntimeException("删除失败");
            }
        }

}
